package outbound

import (
	"bytes"
	"fmt"
	"gateway/config"
	"gateway/core"
	"gateway/util"
	"go.uber.org/zap"
	"io/ioutil"
	"net/http"
	"time"
)

type httpOutbound struct {
	name, host, path, method string
	headers, args            config.Args
}

func newHttpOutbound(name string) core.Outbound {
	return &httpOutbound{
		name:    name,
		headers: config.NewArgs(),
		args:    config.NewArgs(),
	}
}

func (this *httpOutbound) Send(msg core.Message) {
	url := this.host + this.path
	client := http.Client{
		Timeout: time.Minute,
	}
	reader := bytes.NewReader(msg.GetPayload())
	req, _ := http.NewRequest(this.method, url, reader)
	for k, v := range this.headers {
		req.Header.Add(k, v)
	}
	resp, err := client.Do(req)
	if err != nil {
		config.Logger.Warn("Send message error",
			zap.String("method", this.method),
			zap.String("url", url),
			zap.Error(err))
		return
	}
	defer util.Close(resp.Body)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		config.Logger.Warn("Read body error", zap.Error(err))
		return
	}
	config.Logger.Debug("Send message",
		zap.String("method", this.method),
		zap.String("url", url),
		zap.ByteString("body", body))
}

func (this *httpOutbound) SetArgs(args config.Args) {
	this.args.SetArgs(args)
}

func (this *httpOutbound) Initialize() {
	this.host = this.args.GetRequired(HOST)
	this.path = this.args.GetRequired(PATH)
	this.method = this.args.GetRequired(METHOD)
	this.headers, _ = util.ToMap(this.args[HEADERS], ",", "=")
	config.Logger.Info("Initialize HttpOutbound",
		zap.String("name", this.name),
		zap.String("host", this.host),
		zap.String("path", this.path),
		zap.String("method", this.method),
		zap.String("headers", fmt.Sprintf("%v", this.headers)))
}

func (this *httpOutbound) Destroy() {
	config.Logger.Info("Destroy HttpOutbound", zap.String("name", this.name))
}
